package orm

import (
	"animal/octopus/common"
	"animal/octopus/model"

	log "github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func GetTopoModules(db *gorm.DB, topoViewID uint) ([]model.Module, error) {
	var topoView model.TopoView
	if err := common.DB(db).Model(&model.TopoView{}).Preload("Modules").
		First(&topoView, topoViewID).Error; err != nil {
		log.Error("find topo view failed")
		return nil, err
	}

	return topoView.Modules, nil
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func UpdateTopoModule(db *gorm.DB, param common.UpdateTopoModuleParam) error {
	if err := common.DB(db).Transaction(func(tx *gorm.DB) error {
		// check topo view existence
		topoView, ok := common.FindItemByID[model.TopoView](tx, param.TopoViewID)
		if !ok {
			log.WithField("view", param.TopoViewID).Error("cannot find topo view")
			return common.NewErrCode(common.ErrGeneralError)
		}

		var modules []model.Module
		for _, moduleName := range param.Modules {
			if module, ok := common.FindItemByName[model.Module](tx, moduleName); !ok {
				log.Error("find module failed")
				return common.NewErrCode(common.ErrDatabaseError)
			} else {
				modules = append(modules, *module)
			}
		}

		// clear association
		if err := tx.Model(&topoView).Association("Modules").Clear(); err != nil {
			log.Error("clear association failed")
			return common.NewErrCode(common.ErrDatabaseError)
		}

		// build association again
		if err := tx.Model(&topoView).Association("Modules").Append(modules); err != nil {
			log.Error("update topo view failed")
			return err
		}

		return nil
	}); err != nil {
		log.WithField("param", param).Error("update topo view module failed")
		return err
	}

	log.WithField("param", param).Info("update topo view module success")

	return nil
}
